#include "frequencyanalysis.h"

#include "globalDefines.h"

#include <QHash>
#include <QSqlDatabase>
#include <QSqlQuery>
#include <QTextStream>
#include <QtDebug>

#include "binarytextedit.h"

FrequencyAnalysis::FrequencyAnalysis(int freqLen, QByteArray input, QHash<QByteArray, int> frequencies, QObject *parent)
    : QThread(parent), freqLen(freqLen), input(input), frequencies(frequencies) {}

void FrequencyAnalysis::run()
{
    //calculate frequencies
    QByteArray nGram;
//    QHash<QByteArray, int> frequencies;
    int dataLenght = 0;
    foreach (QByteArray letter, frequencies.keys())
        if (letter.length() == 1) dataLenght += frequencies[letter];
    foreach (const unsigned char byte, input)
    {
        nGram.append(byte);
        if (nGram.length() > freqLen)
            nGram.remove(0, 1);
        for (int i = 0; i < nGram.length(); i++)
        {
            frequencies[nGram.right(i + 1)]++;
        }
        dataLenght++;
    }

    //save
    QSqlDatabase db = QSqlDatabase::database();
    if (db.isOpen())
    {
        db.exec("DROP TABLE IF EXISTS frequencies");
        db.exec("CREATE TABLE frequencies (key VARCHAR(" + QString::number(freqLen) + ") PRIMARY KEY, klen INTEGER, absFreq INTEGER, relFreq REAL)");
        foreach (const QByteArray key, frequencies.keys())
        {
            db.exec("INSERT INTO frequencies VALUES ( \""
                    + QString(key) + "\", "
                    + QString::number(key.length()) + ", "
                    + QString::number(frequencies[key]) + ", "
                    + QString::number(qreal(frequencies[key])/qreal(dataLenght))
                    + ")");
        }
        db.close();
    }
    else
    {
        qDebug() << "db not open";
    }

    //formatted output
    QString output;
    QTextStream outputStream(&output);
    QList<QByteArray> keys = frequencies.keys();
    qSort(keys.begin(), keys.end(), lessThanByLenght);

    int l = 1;
    foreach (QByteArray key, keys)
    {
        if (l < key.length())
        {
            outputStream << "\n";
            l = key.length();
        }
        outputStream << "\"" << BinaryTextEdit::escape(key, BinaryTextEdit::CEscape)
                     << "\" => " << QString::number(qreal(frequencies[key])/dataLenght) << "\n";
    }
    outputStream << "\nTotale: " << QString::number(dataLenght);
    outputStream.flush();
    emit done(output);
}
